import json

from flask import request
from flask_appbuilder import BaseView, expose, has_access
from flask_appbuilder.models.sqla.interface import SQLAInterface
from flask_appbuilder.urltools import get_filter_args
from werkzeug.utils import redirect

from app import appbuilder, db, socketio

from app.models import Profile, Condition, CheckUnit, Selector, SerialPort, AppSetting


class RunningView(BaseView):
    route_base = '/running'
    profile = None
    running = dict(title=None, msg=None, clazz=None)

    def load_profile(self, id):
        datamodel = SQLAInterface(Profile, appbuilder.session)
        search_columns = datamodel.get_search_columns_list()
        _filters = datamodel.get_filters(search_columns)
        _filters.clear_filters()
        _filters.add_filter_index('id', 0, id)
        count, lst = datamodel.query(_filters)
        if count:
            return lst[0]
        return None

    def load_app_setting(self):
        datamodel = SQLAInterface(AppSetting, appbuilder.session)
        count, lst = datamodel.query()
        return lst

    def load_conditions(self, selector_id):
        datamodel = SQLAInterface(Condition, appbuilder.session)
        search_columns = datamodel.get_search_columns_list()
        _filters = datamodel.get_filters(search_columns)
        _filters.clear_filters()
        _filters.add_filter_index('selector_id', 0, selector_id)
        return datamodel.query(_filters)

    def load_selectors(self, profile_id):
        datamodel = SQLAInterface(Selector, appbuilder.session)
        search_columns = datamodel.get_search_columns_list()
        _filters = datamodel.get_filters(search_columns)
        _filters.clear_filters()
        _filters.add_filter_index('profile_id', 0, profile_id)
        return datamodel.query(_filters)

    def load_units(self, profile_id):
        datamodel = SQLAInterface(CheckUnit, appbuilder.session)
        search_columns = datamodel.get_search_columns_list()
        _filters = datamodel.get_filters(search_columns)
        _filters.clear_filters()
        _filters.add_filter_index('profile_id', 0, profile_id)
        return datamodel.query(_filters)

    @expose('/test')
    def test(self):
        print('teafas')
        ports = db.session.query(SerialPort)
        if hasattr(appbuilder, 'task'):
            return getattr(appbuilder, 'task')
        return 'no task obj'

    @expose('/info', methods=('GET','POST'))
    def info(self):
        if request.method == 'GET':
            return json.dumps(self.running)
        else:
            title = request.form.get('title')
            msg = request.form.get('msg')
            clazz = request.form.get('clazz')
            if title:
                self.running['title'] = title
            if msg:
                self.running['msg'] = msg
            if clazz:
                self.running['clazz'] = clazz
            if title or msg or clazz:
                socketio.emit('info', self.running, broadcast=True)
            # self.running[]
            # title = None, msg = None, clazz = None
            return 'ok'

    @expose('/')
    def index(self):
        return self.render_template('index.html',
                                    appbuilder=self.appbuilder)

    @expose('/trays')
    # @has_access
    def trays(self):
        alert = None
        profile = None
        trays = dict()
        p = request.args.get('p')
        if not p:
            p = self.profile
        if p:
            profile = self.load_profile(p)
        if profile:
            selectors_count, selectors = self.load_selectors(p)
            trays = dict()
            trays[profile.default_tray_id] = profile.default_tray.name
            for s in selectors:
                trays[s.tray_id] = s.tray.name
        return self.render_template('trays.html',
                                    appbuilder=self.appbuilder,
                                    trays=trays)


    @expose('/profile/detail')
    # @has_access
    def detail(self):
        alert = None
        profile = None
        p = request.args.get('p')
        if not p:
            p = self.profile
        if p:
            profile = self.load_profile(p)
        if profile:
            to_show = dict(name=profile.name, tray=profile.default_tray.name, readme=profile.readme.replace("\n", '<br>'))
            units_count, units = self.load_units(p)
            units_to_show = []
            for u in units:
                units_to_show.append(dict(id=u.id, name=u.name, black=u.black.name, temp=u.temp,
                                          readme=u.readme.replace("\n", "<br>")))
            units_to_show.sort(key=id)
            to_show['units'] = units_to_show
            # list of selectors
            selectors_count, selectors = self.load_selectors(p)
            if selectors_count == 0:
                alert = '尚未配置筛选条件'
                to_show['selectors'] = []
            else:
                # fill conditions by selector
                selectors_to_show = []
                for s in selectors:
                    selector_to_show = dict(weight=s.weight, name=s.name, tray=s.tray.name,
                                            ra=s.resister_a.name, rb=s.resister_b.name, readme=s.readme)
                    conditions_count, conditions = self.load_conditions(s.id)
                    if conditions_count != units_count:
                        alert = '工作场景配置异常'
                    map_conditions = {}
                    for c in conditions:
                        map_conditions[c.unit_id] = dict(name=c.name, va=c.voltage_a.name, vb=c.voltage_b.name,
                                                         readme=c.readme)
                    conditions_to_show = []
                    for u in units_to_show:
                        data = map_conditions.get(u.get('id'))
                        if data:
                            conditions_to_show.append(data)
                        else:
                            conditions_to_show.append('')
                    selector_to_show['conditions']  = conditions_to_show
                    selectors_to_show.append(selector_to_show)
                to_show['selectors'] = selectors_to_show
            return self.render_template('detail.html',
                                        appbuilder=self.appbuilder,
                                        profile=to_show)
        return '<b>请选择工作场景</b>'

    @expose('/profile/load')
    # @has_access
    def load(self):
        datamodel = SQLAInterface(Profile, appbuilder.session)
        _base_filters = datamodel.get_filters()
        list_cols = datamodel.get_columns_list()
        search_columns = datamodel.get_search_columns_list()
        _filters = datamodel.get_filters(search_columns)
        # _filters.clear_filters()
        # _filters.add_filter_index('profile', 0, '1')
        get_filter_args(_filters)
        joined_filters = _filters.get_joined_filters(_base_filters)
        order_column, order_direction = 'id', 'desc'
        profiles = []
        count, lst = datamodel.query(joined_filters, order_column, order_direction)
        for p in lst:
            profiles.append(dict(name=p.name, readme=p.readme.replace("\n", '<br>'),
                                 tray=p.default_tray.name,
                                 link='/running/profile/view?profile=%d'%p.id))
        return self.render_template('load.html',
                                    appbuilder=self.appbuilder,
                                    profiles=profiles)


    @expose('/profile/set')
    # @has_access
    def set(self):
        p = request.args.get('p')
        if p:

            pass
        return redirect('/')


    @expose('/button/click')
    def on_click(self):
        cmd = request.args.get('what')
        appbuilder.task.queue.put((cmd.strip(), None))
        return 'ok'



@socketio.on('connect')
def test_connect():
    print("client connected")

@socketio.on('disconnect')
def test_disconnect():
    print('Client disconnected')


@socketio.on('my event')
def handle_my_custom_event(json):
    socketio.emit('info', 'info from server', broadcast=True)


appbuilder.add_view_no_menu(RunningView, "RunningView")
